#include "content-base.h"

#define recommendFileNum 5
#define userNum 5551
#define fileNum 16980
#define K 100

//int K = 50;


void clearArray(int* array, int len)
{
	for(int i =0; i < len; i++)
	{
		array[i] = 0;
	}
}
void clearArray(double* array, int len)
{
	for (int i = 0; i < len; i ++)
	{
		array[i] = 0;
	}
}

void parseLine(string line, int& userIndex, int& fileName)
{
	int middle = line.find(',');
	string sUserIndex = line.substr(0,middle);
	string sFileName = line.substr(middle+1, line.length()-middle-1);
	userIndex = atoi(sUserIndex.c_str());
	fileName = atoi(sFileName.c_str());
}

void parseUserItemLine(string userItemLine, int userIndex, int* userLikeFile)
{
	int lastComma = -1;
	int comma = 0;
	int len = userItemLine.length();
	for(int i= 0; i < len; i++)
	{
		if(userItemLine[i]==',' || i == len-1)
		{
			if(i == len-1)
				comma = i+1;
			else
				comma=i;
			string oneFile = userItemLine.substr(lastComma+1, comma-lastComma-1);
			int intOneFile = atoi(oneFile.c_str());
			userLikeFile[intOneFile]=1;
			lastComma = comma;
		}
	}
}

void parseSimilary(string line, double* result)
{
	int len = line.length();
	int lastComma = -1;
	int comma = 0;
	int k = 1;

	for(int i= 0; i < len; i++)
	{
		if(line[i]==' ' || i == len-1)
		{
			if(i == len-1)
				comma = i+1;
			else
				comma=i;
			string oneSimi = line.substr(lastComma+1, comma-lastComma-1);
			double intoneSimi = atof(oneSimi.c_str());
			result[k] = intoneSimi;
			k++;
			lastComma = comma;
		}
	}
}

string intToString(int a)
{
	string result = "";
	string temp = "";
	while(a > 0)
	{
		temp = ((a%10)+'0');
		temp +=result;
		result = temp;
		a /= 10;
	}

	return result;
}

double score(int userIndex, int fileName, int* userLikeFile,double* similary)
{

	//Kmost[0] is the best
	int *Kmost = new int[K];
	for(int i = 0; i < K; i ++)
		Kmost[i] = 0;

	int temp = fileName;
	string similaryFile = "result2\\";

	string strTemp = intToString(temp);
	similaryFile += strTemp;
	similaryFile += ".txt";
	ifstream sReader(similaryFile);
	string line;
	getline(sReader, line);

//	double* similary = new double[fileNum+1];
	clearArray(similary, fileNum+1);
	parseSimilary(line, similary);

	for(int i = 1; i < fileName+1; i++)
	{
		for(int j = 0; j < K; j++)
		{
			if(similary[i]>similary[Kmost[j]])
			{
				for(int m = K-1; m > j; m--)
				{
					Kmost[m] = Kmost[m-1];
				}
				Kmost[j] = i;
				break;
			}
		}
	}

	double finalScore = 0;
	for (int i = 0; i < K; i++)
	{
// 		if(userLikeFile[Kmost[i]] == 1)
// 			cout<<Kmost[i]<<endl;
		finalScore += similary[Kmost[i]]*userLikeFile[Kmost[i]];
	}
	sReader.close();
	return finalScore;
}

void newparseSimilary(string line, double* result, int* Karray)
{
	int len = line.length();
	int lastComma = -1;
	int comma = 0;
	int k = 1;
	int m = 0;

	for(int i= 0; i < len; i++)
	{
		if(line[i]==',' || i == len-1)
		{
			if(i == len-1)
				comma = i+1;
			else
				comma=i;

			int middle = line.find(':',lastComma+1);
			string oneFile = line.substr(lastComma+1, middle-lastComma-1);
			int intoneFile = atoi(oneFile.c_str());
			string oneSimi = line.substr(middle+1, comma-middle-1);
			double intoneSimi = atof(oneSimi.c_str());
			Karray[m] = intoneFile;
			m++;
			result[intoneFile] = intoneSimi;

			lastComma = comma;
			if(m >= K)
				break;
		}
	}
}

double newscore(int userIndex, int fileName, int* userLikeFile, double* similary)
{

	//Kmost[0] is the best
	int *Kmost = new int[K];
	for(int i = 0; i < K; i ++)
		Kmost[i] = 0;

	int temp = fileName-1;
	string similaryFile = "result2\\";

	string strTemp = intToString(temp);
	similaryFile += strTemp;
	similaryFile += ".txt";
	ifstream sReader(similaryFile);
	string line;
	getline(sReader, line);

	//double* similary = new double[fileNum+1];
	clearArray(similary, fileNum+1);
	newparseSimilary(line, similary, Kmost);

	double finalScore = 0;
	for (int i = 0; i < K; i++)
	{
		// 		if(userLikeFile[Kmost[i]] == 1)
		// 			cout<<Kmost[i]<<endl;
		finalScore += similary[Kmost[i]]*userLikeFile[Kmost[i]];
	}
	sReader.close();
	return finalScore;
}

void selectCandidate(int userIndex, int* candidateFile, int* recommendFile, int* userLikeFile, double* similary, double* fileSorce)
{
// 	string outputFile = "2\\run2\\filesorce50.txt";
// 	ofstream scoreWriter;
// 	scoreWriter.open(outputFile, ios::in|ios::out|ios::app);
// 
// 	scoreWriter<<"user: "<<userIndex<<endl;

	//double* fileSorce = new double[fileNum+1];
	clearArray(fileSorce, fileNum+1);

	for (int i = 1; i < fileNum+1; i++)
	{
		if(candidateFile[i]==1)
		{
			//how does userindex like file i
			fileSorce[i] = newscore(userIndex, i, userLikeFile, similary);
// 			if(abs(fileSorce[i]) > 0.00000001)
// 				scoreWriter<<i<<":"<<fileSorce[i]<<endl;
		}
	}

/*	scoreWriter.close();*/

	//output the point of every file
	//recommendfile[0] is the best
	for(int i =1; i < fileNum+1;i++)
	{
		for(int j = 0;j<recommendFileNum;j++ )
		{
			if(fileSorce[i]>fileSorce[recommendFile[j]])
			{
				for(int k = recommendFileNum-1; k>j; k--)
				{
					recommendFile[k] = recommendFile[k-1];
				}
				recommendFile[j] = i;
				break;
			}
		}
	}

}
int main()
{
	double totalCorrect = 0;
	bool isFirst = true;
	//string readFileName = "user-info-test.csv";
	//string readFileName = "run2\\user-info-test2.txt";
	string readFileName = "2\\run2\\mytest.txt";
	string outFileName = "2\\run2\\result100.txt";
	string userItemFileName = "user-item-matrix.txt";

	ifstream mfReader(readFileName);
	ofstream mfWriter(outFileName);
	ifstream userItemReader(userItemFileName);
	int userIndex = 1;
	//userFile[i]=1, then userIndex like file i
	int* candidateFile = new int[fileNum+1];
	clearArray(candidateFile, fileNum+1);
	int* recommendFile = new int[recommendFileNum];
	clearArray(recommendFile, recommendFileNum);
	int* userLikeFile = new int[fileNum+1];
	clearArray(userLikeFile, fileNum+1);
	double* similary = new double[fileNum+1];
	clearArray(similary, fileNum+1);
	double* fileSorce = new double[fileNum+1];
	clearArray(fileSorce, fileNum+1);
	while (!mfReader.eof())
	{
		string line;
		getline(mfReader, line);
		int fUserIndex = 0;
		int fFileName = 0;
		parseLine(line, fUserIndex, fFileName);
		if(isFirst)
		{
			userIndex = fUserIndex;
			isFirst = false;
		}

		if(fUserIndex > userIndex)
		{
			//test
			if(userIndex % 50 == 0)
				cout<<userIndex<<endl;

			string userItemLine;
			getline(userItemReader, userItemLine);
			parseUserItemLine(userItemLine, userIndex, userLikeFile);
			selectCandidate(userIndex, candidateFile, recommendFile, userLikeFile, similary, fileSorce);

			//correct rate
			int correctNum = 0;
			int userLikeNum = 0;
			for(int i = 1; i < fileNum+1; i++)
			{
				if(userLikeFile[i] == 1)
					userLikeNum++;
			}
			//ouput
			mfWriter<<userIndex<<",";
			for(int i = 0; i < recommendFileNum; i ++)
			{
				if(i == recommendFileNum-1)
					mfWriter<<recommendFile[i]<<endl;
				else
					mfWriter<<recommendFile[i]<<";";

				if(userLikeFile[recommendFile[i]] == 1)
					correctNum++;
			}

			//compute the correct rate

			totalCorrect += (correctNum+0.0)/(userLikeNum+0.0);


			userIndex++;
			clearArray(candidateFile, fileNum+1);
			clearArray(userLikeFile, fileNum+1);
			clearArray(recommendFile, recommendFileNum);
			candidateFile[fFileName] = 1;
		}
		else
		{
			candidateFile[fFileName] = 1;
		}
	}

	string luserItemLine;
	getline(userItemReader, luserItemLine);
	parseUserItemLine(luserItemLine, userIndex, userLikeFile);
	selectCandidate(userIndex, candidateFile, recommendFile, userLikeFile, similary,fileSorce);
	int luserLikeNum = 0;
	int lcorrectNum = 0;
	for(int i = 1; i < fileNum+1; i++)
	{
		if(userLikeFile[i] == 1)
			luserLikeNum++;
	}
	mfWriter<<userIndex<<",";
	for(int i = 0; i < recommendFileNum; i ++)
	{
		if(i == recommendFileNum-1)
			mfWriter<<recommendFile[i]<<endl;
		else
			mfWriter<<recommendFile[i]<<";";

		if(userLikeFile[recommendFile[i]] == 1)
			lcorrectNum++;
	}

	totalCorrect += (lcorrectNum+0.0)/(luserLikeNum+0.0);
	totalCorrect = totalCorrect/userNum;
	cout<<"k is: "<<K<<", totalCorrect is :"<<totalCorrect<<endl;

	mfReader.close();
	mfWriter.close();
	userItemReader.close();
}